﻿using System;
using System.Collections;
using System.Reflection;
using System.Text;

namespace xshare
{


    public static class DumpUtils
    {

        static StringBuilder s_textBuilder;

        private static void AppendIndent(int num)
        {
            s_textBuilder.Append(' ', num);
        }

        private static void DoDump(bool preComma, object obj)
        {
            if (preComma)
            {
                s_textBuilder.Append(",");
                AppendIndent(1);
            }

            if (obj == null)
            {
                s_textBuilder.Append("null");
                return;
            }

            var t = obj.GetType();

            //repeat field
            if (obj is IList)
            {
                /*
                _text.Append(t.FullName);
                _text.Append(",");
                AppendIndent(1);
                */

                s_textBuilder.Append("[");
                IList list = obj as IList;
                for (var i = 0; i < list.Count; ++i)
                {
                    var v = list[i];
                    if (i > 0)
                        s_textBuilder.Append(", ");

                    DoDump(false, v);
                }

                s_textBuilder.Append("]");
            }
            else if (t.IsValueType)
            {
                s_textBuilder.Append(obj);
            }
            else if (obj is string)
            {
                s_textBuilder.Append("\"");
                s_textBuilder.Append(obj);
                s_textBuilder.Append("\"");
            }
            else if (t.IsArray)
            {
                Array a = (Array)obj;
                s_textBuilder.Append("[");
                for (int i = 0; i < a.Length; i++)
                {
                    if (i > 0)
                        s_textBuilder.Append(", ");

                    s_textBuilder.Append(i);
                    s_textBuilder.Append(":");
                    DoDump(false, a.GetValue(i));
                }

                s_textBuilder.Append("]");
            }
            else if (t.IsClass)
            {
                s_textBuilder.Append($"<{t.Name}>");
                s_textBuilder.Append("{");
                var fields = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                if (fields.Length > 0)
                {
                    for (var i = 0; i < fields.Length; ++i)
                    {
                        var fi = fields[i];

                        if (i > 0)
                            s_textBuilder.Append(", ");

                        s_textBuilder.Append(fi.Name);
                        s_textBuilder.Append(":");
                        object value = fi.GetGetMethod().Invoke(obj, null);
                        DoDump(false, value);
                    }
                }

                s_textBuilder.Append("}");
            }
            else
            {
                Log.w($"DumpUtils: unsupport type: {t.FullName}");

                s_textBuilder.Append(obj);
            }
        }

        public static string DumpAsString(object obj, string hint = "")
        {
            if (null == s_textBuilder)
                s_textBuilder = new StringBuilder("", 1024);
            else
                s_textBuilder.Clear();

            s_textBuilder.Append(hint);
            DoDump(false, obj);
            return s_textBuilder.ToString();
        }


    } //end of class


}